{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "58829f95",
   "metadata": {},
   "source": [
    "# Module 4 - Exploring Image Generation with **Amazon Nova Canvas**\n",
    "\n",
    "---\n",
    "\n",
    "In this hands-on session, we'll explore the powerful capabilities of Amazon Nova Canvas to create compelling visual ads for Octank, a premium dog food company.\n",
    "\n",
    "---\n",
    "\n",
    "### Introduction\n",
    "In this notebook, you'll explore Amazon Nova Canvas, a state-of-the-art image generation model that creates high-quality, photorealistic visuals from text prompts. Nova Canvas supports advanced features such as text-to-image generation, inpainting, outpainting, image variation, and subject consistency. These capabilities make it a powerful tool for applications like product visualization, creative design, and content generation—enabling businesses to produce studio-quality images at scale, accelerate content workflows, and enhance customer experiences with highly tailored visuals.\n",
    "\n",
    "### Use Case\n",
    "Octank is launching a new dog food line and wants to create various visual assets:\n",
    "- Generate an initial product package design\n",
    "- Create variations of the package design, including a oil-painting style version\n",
    "- Design a special promotional package using specific brand colors\n",
    "- Produce a professional-looking ad with the product in a kitchen setting\n",
    "- Isolate the product image for use in various marketing materials\n",
    "\n",
    "### Lab Objectives\n",
    "By the end of this notebook lab, you will:\n",
    "- Understand the key features of Amazon Nova Canvas\n",
    "- Learn how to use these features for a real-world marketing scenario\n",
    "- Gain hands-on experience with the Amazon Bedrock API for image generation tasks\n",
    "\n",
    "## 1. Setup\n",
    "\n",
    "### 1.1 Import Libraries and Init Clients"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "96b28fc1",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Built-in libraries\n",
    "import base64\n",
    "import io\n",
    "import json\n",
    "import os\n",
    "import sys\n",
    "\n",
    "# External dependencies\n",
    "import boto3\n",
    "import botocore\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from PIL import Image\n",
    "\n",
    "# Set up Bedrock client\n",
    "boto3_bedrock = boto3.client('bedrock-runtime')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c99667e1",
   "metadata": {},
   "source": [
    "## 1.2 Implement Helper Functions\n",
    "\n",
    "The following ultilty function visualizes generated images alongside optional reference images. It's essential for displaying and comparing the results of image generation tasks, allowing you to easily see the input, output, and any relevant color information in a single, organized plot."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e030a9aa",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Utility function: Define plot function\n",
    "def plot_images(base_images, prompt=None, seed=None, ref_image_path=None, color_codes=None, original_title=None, processed_title=None):\n",
    "    if ref_image_path and color_codes:\n",
    "        fig, axes = plt.subplots(1, 3, figsize=(15, 5))\n",
    "        num_subplots = 3\n",
    "    elif ref_image_path or color_codes:\n",
    "        fig, axes = plt.subplots(1, 2, figsize=(12, 5))\n",
    "        num_subplots = 2\n",
    "    else:\n",
    "        fig, axes = plt.subplots(1, 1, figsize=(6, 5))\n",
    "        num_subplots = 1\n",
    "    \n",
    "    axes = np.array(axes).ravel() \n",
    "    \n",
    "    current_subplot = 0\n",
    "    \n",
    "    if color_codes:\n",
    "        num_colors = len(color_codes)\n",
    "        color_width = 0.8 / num_colors\n",
    "        for i, color_code in enumerate(color_codes):\n",
    "            x = i * color_width\n",
    "            rect = plt.Rectangle((x, 0), color_width, 1, facecolor=f'{color_code}', edgecolor='white')\n",
    "            axes[current_subplot].add_patch(rect)\n",
    "        axes[current_subplot].set_xlim(0, 0.8)\n",
    "        axes[current_subplot].set_ylim(0, 1)\n",
    "        axes[current_subplot].set_title('Color Codes')\n",
    "        axes[current_subplot].axis('off')\n",
    "        current_subplot += 1\n",
    "    \n",
    "    if ref_image_path:\n",
    "        reference_image = Image.open(ref_image_path)\n",
    "        max_size = (512, 512)\n",
    "        reference_image.thumbnail(max_size)\n",
    "        axes[current_subplot].imshow(np.array(reference_image))\n",
    "        axes[current_subplot].set_title(original_title or 'Reference Image')\n",
    "        axes[current_subplot].axis('off')\n",
    "        current_subplot += 1\n",
    "    \n",
    "    axes[current_subplot].imshow(np.array(base_images[0]))\n",
    "    if processed_title:\n",
    "        axes[current_subplot].set_title(processed_title)\n",
    "    elif ref_image_path and seed is not None:\n",
    "        axes[current_subplot].set_title(f'Image Generated Based on Reference\\nSeed: {seed}')\n",
    "    elif seed is not None:\n",
    "        axes[current_subplot].set_title(f'Image Generated\\nSeed: {seed}')\n",
    "    else:\n",
    "        axes[current_subplot].set_title('Processed Image')\n",
    "    axes[current_subplot].axis('off')\n",
    "    \n",
    "    if prompt:\n",
    "        print(f\"Prompt: {prompt}\\n\")\n",
    "    \n",
    "    plt.tight_layout()\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "caf02373",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "def save_image(base64_image, output_file):\n",
    "    with open(output_file, 'wb') as file:\n",
    "        file.write(base64.b64decode(base64_image))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1f87cfb9",
   "metadata": {},
   "source": [
    "## 2. Use Cases Implementation\n",
    "\n",
    "### 2.1 Example: Text to Image\n",
    "\n",
    "\n",
    "#### Scenario\n",
    "Octank wants to generate an initial product package design based on a text description.\n",
    "\n",
    "#### Parameters\n",
    "1. **prompt**: Describes the desired image\n",
    "2. **negative_prompts**: Specifies elements to avoid in the image\n",
    "3. **seed**: For reproducibility\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6aae708c",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt\n",
    "prompt = \"A white packet of premium dog food with an American Eskimo dog on it, professional product photography. Dog food is named Octank.\"\n",
    "negative_prompts = \"poorly rendered, poor background details, poor packet details, poor text details, bleary text\"\n",
    "seed = 42\n",
    "\n",
    "# Specify path to store the output\n",
    "output_save_path = \"images/after_text-to-image.png\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a87a6bf",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Generate text-to-image\n",
    "body = json.dumps(\n",
    "    {\n",
    "        \"taskType\": \"TEXT_IMAGE\",\n",
    "        \"textToImageParams\": {\n",
    "            \"text\": prompt,                    # Required\n",
    "            \"negativeText\": negative_prompts   # Optional\n",
    "        },\n",
    "        \"imageGenerationConfig\": {\n",
    "            \"numberOfImages\": 1,   # Range: 1 to 5 \n",
    "            \"quality\": \"standard\",  # Options: standard or premium\n",
    "            \"height\": 1024,        \n",
    "            \"width\": 1024,         \n",
    "            \"cfgScale\": 7.5,       # Range: 1.0 (exclusive) to 10.0\n",
    "            \"seed\": 250 #100            # Range: 0 to 214783647\n",
    "        }\n",
    "    }\n",
    ")\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "# save output\n",
    "save_image(response_body.get(\"images\")[0], output_save_path)\n",
    "\n",
    "# Plot output\n",
    "plot_images(response_images, processed_title=\"Generated Product Package\") "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0265cb2b",
   "metadata": {},
   "source": [
    "### 2.2 Example: Image Conditioning\n",
    "\n",
    "#### Scenario\n",
    "Octank wants to create a oil-painting version of their package design while maintaining the overall layout.\n",
    "\n",
    "#### Parameters\n",
    "\n",
    "1. **prompt**: Describes the desired style\n",
    "2. **reference_image_path**: Path to the original package design\n",
    "3. **controlMode**: Specifies the conditioning mode (CANNY_EDGE or SEGMENTATION)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6c270d61",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt, reference image\n",
    "prompt = \"a oil-painting dog food packet with a white american eskimo on the packet cover, dog food company name is Octank\"\n",
    "reference_image_path = \"images/after_text-to-image.png\"\n",
    "seed = 42# Can be any random number between 0 to 214783647\n",
    "\n",
    "# Specify path to store the output\n",
    "output_save_path = \"images/after_image_cartooning.png\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d093db9",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Encode the reference image\n",
    "with open(reference_image_path, \"rb\") as image_file:\n",
    "    reference_image_base64 = base64.b64encode(image_file.read()).decode(\"utf-8\")\n",
    "    \n",
    "# Generate image condition on reference image\n",
    "body = json.dumps(\n",
    "    {\n",
    "        \"taskType\": \"TEXT_IMAGE\",\n",
    "        \"textToImageParams\": {\n",
    "            \"text\": prompt,  # Required\n",
    "            \"conditionImage\": reference_image_base64, # Optional\n",
    "            \"controlMode\": \"CANNY_EDGE\", # Optional: CANNY_EDGE | SEGMENTATION\n",
    "            \"controlStrength\": 0.7,  # Range: 0.2 to 1.0,\n",
    "        },\n",
    "        \"imageGenerationConfig\": {\n",
    "                \"numberOfImages\": 1,\n",
    "                \"seed\": seed,\n",
    "            }\n",
    "        \n",
    "    }\n",
    ")\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "save_image(response_body.get(\"images\")[0], output_save_path)\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, ref_image_path = reference_image_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a587c9a4",
   "metadata": {},
   "source": [
    "### 2.3 Example: Image Variation\n",
    "\n",
    "#### Scenario\n",
    "Generating images from text is powerful but, in some cases, you will want your model to understand the style from certain image and directly transfer it to your output image. Rather than starting from scratch, image variation features enables us to do style transfer easily.\n",
    "\n",
    "Now, Octank wants to have a dog food packet with the same style showing in the reference image, let's see how easy this step could be.\n",
    "\n",
    "#### Parameters\n",
    "\n",
    "1. **prompt**: Describes the desired output\n",
    "2. **reference_image_path**: Path to the reference style"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "160ffd82",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt, reference image\n",
    "prompt = \"A white packet of premium dog food with an American Eskimo dog on it, professional product photography. Dog food is named Octank\"\n",
    "negative_prompt = \"bad quality, low resolution\"\n",
    "reference_image_path = \"images/sketch_dog.png\"\n",
    "seed = 600 # Can be any random number between 0 to 214783647\n",
    "\n",
    "# Specify path to store the output\n",
    "output_save_path = \"images/after_image_variation.png\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9fbdae0",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Encode the reference image\n",
    "with open(reference_image_path, \"rb\") as image_file:\n",
    "    reference_image_base64 = base64.b64encode(image_file.read()).decode(\"utf-8\")\n",
    "\n",
    "body = json.dumps({\n",
    "     \"taskType\": \"IMAGE_VARIATION\",\n",
    "     \"imageVariationParams\": {\n",
    "         \"text\": prompt,              # Optional\n",
    "         \"negativeText\": negative_prompt,   # Optional\n",
    "         \"images\": [reference_image_base64],               # One image is required\n",
    "        #  \"similarityStrength\": 1.0\n",
    "     },\n",
    "     \"imageGenerationConfig\": {\n",
    "         \"numberOfImages\": 1,\n",
    "         \"quality\": \"premium\",\n",
    "         \"height\": 1024,\n",
    "         \"width\": 1024,\n",
    "         #\"cfgScale\": 10,\n",
    "         \"seed\": seed\n",
    "     }\n",
    " })\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "save_image(response_body.get(\"images\")[0], output_save_path)\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, ref_image_path = reference_image_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59793dbf",
   "metadata": {},
   "source": [
    "### 2.4 Example: Inpainting\n",
    "\n",
    "#### Scenario\n",
    "Octank has decided to refresh their product line by featuring different dog breeds on their packaging. However, they want to maintain consistency in the overall design and only change the dog image. This is where inpainting comes in handy. For this task, Octank wants to replace the American Eskimo dog on their current packaging with a Husky, while keeping the rest of the design intact.\n",
    "\n",
    "Let's use inpainting to help Octank update their packaging with a new dog breed.\n",
    "\n",
    "#### Parameters\n",
    "\n",
    "1. **prompt**: Describes the desired output\n",
    "2. **reference_image_path**: Path to the reference style\n",
    "3. **mask_prompt**: Describe the object to be replaced"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4fea1698",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt and reference image\n",
    "prompt = \"A white packet of premium dog food with Husky dog on it, professional product photography. Dog food is named Octank\"\n",
    "negative_prompts = \"bad quality, low res\"\n",
    "reference_image_path = \"images/after_image_cartooning.png\" \n",
    "mask_prompt = \"American Eskimo dog\"\n",
    "seed = 2 # Can be any random number between 0 to 214783647"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3a339e49",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "with open(reference_image_path, \"rb\") as image_file:\n",
    "    reference_image_base64 = base64.b64encode(image_file.read()).decode(\"utf-8\")\n",
    "\n",
    "    \n",
    "# Generate image condition on reference image\n",
    "body = json.dumps(\n",
    "    {\n",
    "        \"taskType\": \"INPAINTING\",\n",
    "        \"inPaintingParams\": {\n",
    "            \"text\": prompt,  # Optional - what to change inside the mask\n",
    "            \"negativeText\": negative_prompts,    # Optional\n",
    "            \"image\": reference_image_base64,  # Required\n",
    "            \"maskPrompt\": mask_prompt,  # One of \"maskImage\" or \"maskPrompt\" is required\n",
    "            # \"maskImage\": \"base64-encoded string\",   \n",
    "\n",
    "        },\n",
    "        \"imageGenerationConfig\": {\n",
    "                \"numberOfImages\": 1,\n",
    "                \"seed\": seed,\n",
    "            }\n",
    "    }\n",
    ")\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, ref_image_path = reference_image_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2b1029d",
   "metadata": {},
   "source": [
    "### 2.5 Example: Color Conditioning\n",
    "\n",
    "#### Scenario\n",
    "Now, let's create a special promotional package design using Octank's brand color palette.\n",
    "\n",
    "#### Parameters\n",
    "\n",
    "1. **prompt**: Describes the desired output\n",
    "2. **hex_color_code**: Provide reference hex color codes"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c63c58f6",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt, reference image, color code and path to store the generated images\n",
    "prompt = \"A white packet of premium dog food with an American Eskimo dog on it, professional product photography. Dog food is named Octank.\"\n",
    "hex_color_code = [\"#81FC81\", \"#C9D688\", \"#FFFFFF\"]\n",
    "seed = 42 # Can be any random number between 0 to 214783647\n",
    "\n",
    "output_save_path = \"images/after_color_conditioning.png\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f4f6ab4e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Encode the reference image\n",
    "with open(reference_image_path, \"rb\") as image_file:\n",
    "    reference_image_base64 = base64.b64encode(image_file.read()).decode(\"utf-8\")\n",
    "    \n",
    "    \n",
    "# Generate image condition on color palette\n",
    "body = json.dumps({\n",
    "    \"taskType\": \"COLOR_GUIDED_GENERATION\",\n",
    "    \"colorGuidedGenerationParams\": {\n",
    "        \"text\": prompt,\n",
    "        \"colors\": hex_color_code,\n",
    "    },\n",
    "    \"imageGenerationConfig\": {\n",
    "        \"numberOfImages\": 1,\n",
    "        \"seed\": seed,\n",
    "    }\n",
    "})\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "save_image(response_body.get(\"images\")[0], output_save_path)\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, color_codes = hex_color_code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0db52288",
   "metadata": {},
   "source": [
    "### 2.6 Example: Outpainting\n",
    "\n",
    "#### Scenario\n",
    "Now, Octank wants to create a professional-looking ad with this new product with kitchen background. To do this kind of background replacement, we will use the outpainting feature offered by Nova Canvas models. \n",
    "\n",
    "We will first expand the image size to provide more room, then generating the new image using outpainting feature.\n",
    "\n",
    "#### Parameters\n",
    "\n",
    "1. **prompt**: Describes the desired output\n",
    "2. **reference_image_path**: Path to image that will be edit\n",
    "3. **mask_prompt**: Describe the area on the image that will not be edited"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e79dd131",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt and reference image\n",
    "prompt = \"Dog food packet on a kitchen countertop\"\n",
    "reference_image_path = \"images/after_color_conditioning.png\" \n",
    "mask_prompt = \"Dog food packet\"\n",
    "seed = 100 # Can be any random number between 0 to 214783647\n",
    "\n",
    "# Expansion setting\n",
    "target_width = 2048\n",
    "target_height = 2048\n",
    "horizontal_position_percent=0.3\n",
    "vertical_position_percent=0.5\n",
    "\n",
    "output_save_path = \"images/after_outpainting.png\" \n",
    "\n",
    "# Specify path to store the output\n",
    "expand_image_path = \"images/expanded_image.png\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "833e8041",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Load reference image\n",
    "original_image = Image.open(reference_image_path)\n",
    "original_width, original_height = original_image.size\n",
    "\n",
    "# Calculate the position of the original image on the expanded canvas.\n",
    "position = (\n",
    "    int((target_width - original_width) * horizontal_position_percent),\n",
    "    int((target_height - original_height) * vertical_position_percent),\n",
    ")\n",
    "\n",
    "# Create an input image which contains the original image with an expanded\n",
    "# canvas.\n",
    "input_image = Image.new(\"RGB\", (target_width, target_height), (235, 235, 235))\n",
    "input_image.paste(original_image, position)\n",
    "input_image.save(expand_image_path)\n",
    "    \n",
    "# Encode the reference image\n",
    "with open(expand_image_path, \"rb\") as image_file:\n",
    "    reference_image_base64 = base64.b64encode(image_file.read()).decode(\"utf-8\")\n",
    "\n",
    "    \n",
    "# Generate image condition on reference image\n",
    "body = json.dumps(\n",
    "    {\n",
    "        \"taskType\": \"OUTPAINTING\",\n",
    "        \"outPaintingParams\": {\n",
    "            \"text\": prompt,  # Required\n",
    "            \"image\": reference_image_base64,  # Required\n",
    "            \"maskPrompt\": mask_prompt,  # One of \"maskImage\" or \"maskPrompt\" is required\n",
    "            \"outPaintingMode\": \"PRECISE\",  # One of \"PRECISE\" or \"DEFAULT\"\n",
    "        },\n",
    "        \"imageGenerationConfig\": {\n",
    "                \"numberOfImages\": 1,\n",
    "                \"seed\": seed,\n",
    "            }\n",
    "        \n",
    "    }\n",
    ")\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "save_image(response_body.get(\"images\")[0], output_save_path)\n",
    "\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, ref_image_path = reference_image_path)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ddc7e20a",
   "metadata": {},
   "source": [
    "### 2.7 Example: Background Removal\n",
    "\n",
    "#### Scenario\n",
    "Octank has professional photos of their existing gourmet dog food. They want to use these images across various marketing materials with different background. In our last use case, we will use Background Removal feature from Amazon Nova Canvas to help Ocktank isolate its product image from their original backgrond.\n",
    "\n",
    "To use this feature, you just need to provide the image the model needs to work with. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "af3b109e",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define image needs to be processed and path to store the generated images\n",
    "reference_image_path = \"images/after_outpainting.png\" "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "08084f88",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Read image from file and encode it as base64 string.\n",
    "with open(reference_image_path, \"rb\") as image_file:\n",
    "    input_image = base64.b64encode(image_file.read()).decode('utf8')\n",
    "\n",
    "body = json.dumps({\n",
    "    \"taskType\": \"BACKGROUND_REMOVAL\",\n",
    "    \"backgroundRemovalParams\": {\n",
    "        \"image\": input_image,\n",
    "    }\n",
    "})\n",
    "\n",
    "response = boto3_bedrock.invoke_model(\n",
    "    body=body, \n",
    "    modelId=\"amazon.nova-canvas-v1:0\",\n",
    "    accept=\"application/json\", \n",
    "    contentType=\"application/json\"\n",
    ")\n",
    "\n",
    "response_body = json.loads(response.get(\"body\").read())\n",
    "response_images = [\n",
    "    Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "    for base64_image in response_body.get(\"images\")\n",
    "]\n",
    "\n",
    "# plot output\n",
    "plot_images(response_images, ref_image_path= reference_image_path, original_title='Original Image', processed_title='Processed Image without Background')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f95d122b-f24b-4232-8451-cd36f95f17b6",
   "metadata": {},
   "source": [
    "## 3. Responsible AI in Action\n",
    "\n",
    "To continue supporting best practices in the responsible use of AI, Amazon Nova Canvas has built to detect and remove harmful content in the data, reject inappropriate content in the user input, and filter the models’ outputs that contain inappropriate content (such as hate speech, profanity, and violence). \n",
    "\n",
    "Octank marketing team wants generate an appealing campaign by placing and image of Scooby Doo on the package. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d400e126-c157-4def-89d2-44fd0d303ee7",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Define the prompt with some inputs blocked for being copyright image.\n",
    "prompt = \"A white packet of premium dog food with Scooby Doo on it, professional product photography. Dog food is named Octank.\"\n",
    "negative_prompts = \"poorly rendered, poor background details, poor packet details, poor text details, bleary text\"\n",
    "seed = 42"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b84d54e6-8b18-4e83-92ca-80014eec3f48",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Generate text-to-image\n",
    "body = json.dumps(\n",
    "    {\n",
    "        \"taskType\": \"TEXT_IMAGE\",\n",
    "        \"textToImageParams\": {\n",
    "            \"text\": prompt,                    # Required\n",
    "            \"negativeText\": negative_prompts   # Optional\n",
    "        },\n",
    "        \"imageGenerationConfig\": {\n",
    "            \"numberOfImages\": 1,   # Range: 1 to 5 \n",
    "            \"quality\": \"standard\",  # Options: standard or premium\n",
    "            \"height\": 1024,       \n",
    "            \"width\": 1024,         \n",
    "            \"cfgScale\": 7.5,       # Range: 1.0 (exclusive) to 10.0\n",
    "            \"seed\": 42             # Range: 0 to 214783647\n",
    "        }\n",
    "    }\n",
    ")\n",
    "\n",
    "try:\n",
    "    response = boto3_bedrock.invoke_model(\n",
    "        body=body, \n",
    "        modelId=\"amazon.nova-canvas-v1:0\",\n",
    "        accept=\"application/json\", \n",
    "        contentType=\"application/json\"\n",
    "    )\n",
    "    response_body = json.loads(response.get(\"body\").read())\n",
    "    response_images = [\n",
    "        Image.open(io.BytesIO(base64.b64decode(base64_image)))\n",
    "        for base64_image in response_body.get(\"images\")\n",
    "    ]\n",
    "\n",
    "    # Plot output\n",
    "    plot_images(response_images, processed_title=\"Generated Product Package\")     \n",
    "\n",
    "# Handle ValidationException (Responsible AI)\n",
    "except boto3_bedrock.exceptions.ValidationException as error:\n",
    "    print(f\"An error occurred: {error}\")\n",
    "\n",
    "# Handle all the other errors\n",
    "except Exception as e:\n",
    "    # Handle any other unexpected exceptions\n",
    "    print(f\"An unexpected error occurred: {e}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fe27821d-0dce-4bca-95a8-2fe0f939ac2a",
   "metadata": {},
   "source": [
    "**Note that:** Amazon Bedrock gives validation error as the input prompt is asking for images of Scooby Dog and hence violates copyright."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ec210f22",
   "metadata": {},
   "source": [
    "## 4. Summary and Next Steps"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "78849103",
   "metadata": {},
   "source": [
    "In this notebook lab, we explored the powerful features of Amazon Nova Cnavas through the lens of Octank, a premium dog food company. We covered:\n",
    "\n",
    "- Text to Image\n",
    "- Image Conditioning\n",
    "- Color Variation\n",
    "- Inpainting\n",
    "- Color Conditioning\n",
    "- Outpainting\n",
    "- Background Removal\n",
    "- Responsible AI in action\n",
    "\n",
    "These tools enable Octank to efficiently create diverse, high-quality visuals for their marketing campaigns, maintaining brand consistency while adapting to various styles.\n",
    "\n",
    "You can now leverage this GenAI-powered image generation to enhance your own creative workflows!\n",
    "\n",
    "### Next Steps\n",
    "\n",
    "If you want to know more about video generation, please head to the next notebook lab to explore how to create video contents for Octank Dog Food company!\n",
    "\n",
    "&nbsp; **NEXT ▶** [3_nova-reel-lab.ipynb](./3\\_nova-reel-lab.ipynb)."
   ]
  }
 ],
 "metadata": {
  "availableInstances": [
   {
    "_defaultOrder": 0,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.t3.medium",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 1,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.t3.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 2,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.t3.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 3,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.t3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 4,
    "_isFastLaunch": true,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 5,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 6,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 7,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 8,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 9,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 10,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 11,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 12,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.m5d.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 13,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.m5d.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 14,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.m5d.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 15,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.m5d.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 16,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.m5d.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 17,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.m5d.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 18,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.m5d.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 19,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.m5d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 20,
    "_isFastLaunch": false,
    "category": "General purpose",
    "gpuNum": 0,
    "hideHardwareSpecs": true,
    "memoryGiB": 0,
    "name": "ml.geospatial.interactive",
    "supportedImageNames": [
     "sagemaker-geospatial-v1-0"
    ],
    "vcpuNum": 0
   },
   {
    "_defaultOrder": 21,
    "_isFastLaunch": true,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 4,
    "name": "ml.c5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 22,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 8,
    "name": "ml.c5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 23,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.c5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 24,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.c5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 25,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 72,
    "name": "ml.c5.9xlarge",
    "vcpuNum": 36
   },
   {
    "_defaultOrder": 26,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 96,
    "name": "ml.c5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 27,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 144,
    "name": "ml.c5.18xlarge",
    "vcpuNum": 72
   },
   {
    "_defaultOrder": 28,
    "_isFastLaunch": false,
    "category": "Compute optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.c5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 29,
    "_isFastLaunch": true,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g4dn.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 30,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g4dn.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 31,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g4dn.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 32,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g4dn.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 33,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g4dn.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 34,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g4dn.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 35,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 61,
    "name": "ml.p3.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 36,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 244,
    "name": "ml.p3.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 37,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 488,
    "name": "ml.p3.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 38,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.p3dn.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 39,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.r5.large",
    "vcpuNum": 2
   },
   {
    "_defaultOrder": 40,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.r5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 41,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.r5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 42,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.r5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 43,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.r5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 44,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.r5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 45,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.r5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 46,
    "_isFastLaunch": false,
    "category": "Memory Optimized",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.r5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 47,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 16,
    "name": "ml.g5.xlarge",
    "vcpuNum": 4
   },
   {
    "_defaultOrder": 48,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.g5.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 49,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 64,
    "name": "ml.g5.4xlarge",
    "vcpuNum": 16
   },
   {
    "_defaultOrder": 50,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 128,
    "name": "ml.g5.8xlarge",
    "vcpuNum": 32
   },
   {
    "_defaultOrder": 51,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 1,
    "hideHardwareSpecs": false,
    "memoryGiB": 256,
    "name": "ml.g5.16xlarge",
    "vcpuNum": 64
   },
   {
    "_defaultOrder": 52,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 192,
    "name": "ml.g5.12xlarge",
    "vcpuNum": 48
   },
   {
    "_defaultOrder": 53,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 4,
    "hideHardwareSpecs": false,
    "memoryGiB": 384,
    "name": "ml.g5.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 54,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 768,
    "name": "ml.g5.48xlarge",
    "vcpuNum": 192
   },
   {
    "_defaultOrder": 55,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4d.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 56,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 8,
    "hideHardwareSpecs": false,
    "memoryGiB": 1152,
    "name": "ml.p4de.24xlarge",
    "vcpuNum": 96
   },
   {
    "_defaultOrder": 57,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 32,
    "name": "ml.trn1.2xlarge",
    "vcpuNum": 8
   },
   {
    "_defaultOrder": 58,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1.32xlarge",
    "vcpuNum": 128
   },
   {
    "_defaultOrder": 59,
    "_isFastLaunch": false,
    "category": "Accelerated computing",
    "gpuNum": 0,
    "hideHardwareSpecs": false,
    "memoryGiB": 512,
    "name": "ml.trn1n.32xlarge",
    "vcpuNum": 128
   }
  ],
  "instance_type": "ml.t3.medium",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.11"
  },
  "toc-autonumbering": false,
  "toc-showcode": false
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
